using System;
using System.Runtime.Remoting;
using System.Collections;
using System.Data.SqlClient;
using System.Collections.Generic;

namespace OnlinePayments
{
	public struct CustomerInfo
	{
		public string FirstName;
		public string LastName;
		public string Address;
		public string City;
		public string State;
		public string Zip;
		public string Country;
		public string CardNumber;
		public object CardExpiration;
		public string CVV2;
	}

	/// <summary>
	/// Summary description for Class1.
	/// </summary>
	public class PaymentProcessor
	{
		private PaymentProcessor _paymentProcessor = null;
		protected bool _test = false;
        private int _paymentSystemID = 0;
        protected string _className = null;
        protected Dictionary<string, string> _configStrings = new Dictionary<string, string>();
        protected SqlConnection _conn;

        public static PaymentProcessor CreatePaymentProcessor(int paymentSystemID)
        {
            SqlConnection conn = new SqlConnection(@"context connection=true");
            conn.Open();

            SqlCommand cmm = conn.CreateCommand();
            cmm.CommandText = "select dbo.Decrypt(Value) from tblPaymentSystemConfig where Name = 'ClassName' and PaymentSystemID = " + paymentSystemID.ToString();
            SqlDataReader rdr = cmm.ExecuteReader();
            if (!rdr.Read())
                throw new Exception("Missing ClassName for payment system " + paymentSystemID.ToString());
            string className = rdr.GetString(0);
            rdr.Close();

            ObjectHandle handle = System.Activator.CreateInstance(null,
                (string)className,
                true,
                0,
                null,
                new object[] { paymentSystemID },
                null, null, null);

            if (handle == null)
                throw new Exception("Error creating payment processor class " + className);
            return (PaymentProcessor)handle.Unwrap();
        }

		public PaymentProcessor( int paymentSystemID ) 
		{
            _paymentSystemID = paymentSystemID;

            _conn = new SqlConnection(@"context connection=true");
            _conn.Open();

            SqlCommand cmm = _conn.CreateCommand();
            cmm.CommandText = "select Name, dbo.Decrypt(Value) from tblPaymentSystemConfig where PaymentSystemID = " + paymentSystemID.ToString();
            SqlDataReader rdr = cmm.ExecuteReader();
            _configStrings = new Dictionary<string, string>();
            while (rdr.Read())
                _configStrings.Add(rdr.GetString(0), rdr.GetString(1));
            rdr.Close();

            _test = _configStrings.ContainsKey("Test");
        }

		public virtual bool Authorize( CustomerInfo customerInfo, 
			Int32 transactionID, 
			decimal amount, 
			out string responseCode,
			out string responseText,
			out string AVSResult,
			out string CVV2Response,
			out string processorTransactionID,
			out string authCode 
			)
		{
			return _paymentProcessor.Authorize( 
				customerInfo, 
				transactionID, 
				amount, 
				out responseCode, 
				out responseText, 
				out AVSResult,
				out CVV2Response,
				out processorTransactionID,
				out authCode );
		}

		public virtual bool Deposit( CustomerInfo customerInfo, 
			Int32 transactionID, 
			decimal amount, 
			out string responseCode,
			out string responseText,
			out string AVSResult,
			out string CVV2Response,
			out string processorTransactionID 
			)
		{
			return _paymentProcessor.Deposit(
				customerInfo, 
				transactionID, 
				amount, 
				out responseCode,
				out responseText,
				out AVSResult,
				out CVV2Response,
				out processorTransactionID );
		}

		public virtual bool DepositWithPriorAuth( CustomerInfo customerInfo, 
			Int32 transactionID, 
			decimal amount, 
			string processorTransactionID,
			string authCode,
			out string responseCode,
			out string responseText,
			out string AVSResult,
			out string CVV2Response
			)
		{
			return _paymentProcessor.DepositWithPriorAuth(
				customerInfo,
				transactionID, 
				amount, 
				processorTransactionID,
				authCode,
				out responseCode,
				out responseText,
				out AVSResult,
				out CVV2Response );
		}

		public virtual bool Refund( CustomerInfo customerInfo, 
			Int32 transactionID, 
			decimal amount, 
			string processorTransactionID,
			out string responseCode,
			out string responseText
			)
		{
			return _paymentProcessor.Refund(
				customerInfo, 
				transactionID, 
				amount, 
				processorTransactionID,
				out responseCode,
				out responseText );
		}
	}
}
